/*
 * To change this template, choose Tools | Templates and open the template in the editor.
 */

package com.bekvon.bukkit.residence.permissions;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;

import org.bukkit.Server;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;

import com.bekvon.bukkit.residence.protection.FlagPermissions;

import pw.yumc.Residence.ResidenceMain;
import pw.yumc.Residence.vaultinterface.ResidenceVaultAdapter;

/**
 *
 * @author Administrator
 */
public class PermissionManager {
    protected static PermissionsInterface perms;
    protected FlagPermissions globalFlagPerms;
    protected Map<String, PermissionGroup> groups;
    protected Map<String, String> playersGroup;
    ResidenceMain plugin;

    public PermissionManager(final ResidenceMain plugin) {
        try {
            this.plugin = plugin;
            groups = Collections.synchronizedMap(new HashMap<String, PermissionGroup>());
            playersGroup = Collections.synchronizedMap(new HashMap<String, String>());
            globalFlagPerms = new FlagPermissions();
            this.readConfig(plugin.getConfig());
            final boolean enable = plugin.getConfig().getBoolean("Global.EnablePermissions", true);
            if (enable) {
                this.checkPermissions();
            }
        } catch (final Exception ex) {
            plugin.getLogger().log(Level.SEVERE, "权限管理载入失败,请报告以下错误给作者,谢谢!", ex);
        }
    }

    public FlagPermissions getAllFlags() {
        return globalFlagPerms;
    }

    public PermissionGroup getGroup(final Player player) {
        return groups.get(this.getGroupNameByPlayer(player));
    }

    public PermissionGroup getGroup(final String player, final String world) {
        return groups.get(this.getGroupNameByPlayer(player, world));
    }

    public PermissionGroup getGroupByName(String group) {
        group = group.toLowerCase();
        if (!groups.containsKey(group)) {
            return groups.get(plugin.getConfigManager().getDefaultGroup());
        }
        return groups.get(group);
    }

    public String getGroupNameByPlayer(final Player player) {
        return this.getGroupNameByPlayer(player.getName(), player.getWorld().getName());
    }

    public String getGroupNameByPlayer(String player, final String world) {
        player = player.toLowerCase();
        if (playersGroup.containsKey(player)) {
            String group = playersGroup.get(player);
            if (group != null) {
                group = group.toLowerCase();
                if (group != null && groups.containsKey(group)) {
                    return group;
                }
            }
        }
        final String group = this.getPermissionsGroup(player, world);
        if (group == null || !groups.containsKey(group)) {
            return plugin.getConfigManager().getDefaultGroup().toLowerCase();
        }
        return group;
    }

    public String getPermissionsGroup(final Player player) {
        return this.getPermissionsGroup(player.getName(), player.getWorld().getName());
    }

    public String getPermissionsGroup(final String player, final String world) {
        if (perms == null) {
            return plugin.getConfigManager().getDefaultGroup();
        }
        return perms.getPlayerGroup(player, world);
    }

    public PermissionsInterface getPermissionsPlugin() {
        return perms;
    }

    public boolean hasGroup(String group) {
        group = group.toLowerCase();
        return groups.containsKey(group);
    }

    public boolean isResidenceAdmin(final Player player) {
        return (player.hasPermission("residence.admin") || (player.isOp() && plugin.getConfigManager().getOpsAreAdmins()));
    }

    private void checkPermissions() {
        final Server server = plugin.getServer();
        final Plugin p = server.getPluginManager().getPlugin("Vault");
        if (p != null) {
            final ResidenceVaultAdapter vault = new ResidenceVaultAdapter(server);
            if (vault.permissionsOK()) {
                perms = vault;
                plugin.getLogger().info("发现 Vault 使用权限系统: " + vault.getPermissionsName());
                return;
            }
            plugin.getLogger().info("发现 Vault, 但是 Vault 未找到权限系统...");
        }
    }

    private void readConfig(final FileConfiguration config) {
        final String defaultGroup = plugin.getConfigManager().getDefaultGroup();
        globalFlagPerms = FlagPermissions.parseFromConfigNode("FlagPermission", config.getConfigurationSection("Global"));
        final ConfigurationSection nodes = config.getConfigurationSection("Groups");
        if (nodes != null) {
            final Set<String> entrys = nodes.getKeys(false);
            for (final String key : entrys) {
                try {
                    groups.put(key.toLowerCase(), new PermissionGroup(key.toLowerCase(), nodes.getConfigurationSection(key), globalFlagPerms));
                    final List<String> mirrors = nodes.getConfigurationSection(key).getStringList("Mirror");
                    for (final String group : mirrors) {
                        groups.put(group.toLowerCase(), new PermissionGroup(key.toLowerCase(), nodes.getConfigurationSection(key), globalFlagPerms));
                    }
                } catch (final Exception ex) {
                    plugin.getLogger().info("错误 从配置文件读取:" + key + " 抛出异常:" + ex);
                }
            }
        }
        if (!groups.containsKey(defaultGroup)) {
            groups.put(defaultGroup, new PermissionGroup(defaultGroup));
        }
        final Set<String> keys = config.getConfigurationSection("GroupAssignments").getKeys(false);
        if (keys != null) {
            for (final String key : keys) {
                playersGroup.put(key.toLowerCase(), config.getString("GroupAssignments." + key, defaultGroup).toLowerCase());
            }
        }
    }
}
